home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / OpenGL / OPENGL2.EXE / _SETUP.1 / indexfnc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-21  |  12.0 KB  |  496 lines

  1. /* indexfnc.c */
  2.  
  3. /*
  4.  * Test/demo of the GL_SGI_index_func extension
  5.  *
  6.  * This extension adds the glIndexFuncSGI() function which let's
  7.  * one cull fragments depending on the fragment's index value
  8.  * compared to a reference value, very much like glAlphaFunc().
  9.  *
  10.  * This demo draws a line, triangle, and image using a ramp of
  11.  * color indexes.  The space bar enables/disables the index test.
  12.  */
  13.  
  14. #include <assert.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <math.h>
  18. #include <windows.h>
  19. #include "GL/gl.h"
  20.  
  21. #if defined(GL_SGI_index_func)
  22. /* Have to access glIndexFuncSGI through a pointer, ugh! */
  23. static PFNGLINDEXFUNCSGIPROC glIndexFuncSGIptr;
  24. #endif
  25.  
  26. char *className = "OpenGL";
  27. char *windowName = "Index Func";
  28. int winX = 0, winY = 0;
  29. int winWidth = 300, winHeight = 300;
  30.  
  31. HDC hDC;
  32. HGLRC hGLRC;
  33. HPALETTE hPalette;
  34.  
  35. void (*idleFunc)(void);
  36.  
  37. void setPaletteIndex(int i, float r, float g, float b);
  38.  
  39. static GLfloat Zrot = 0.0F;
  40. static GLboolean DoTest = GL_FALSE;
  41. static GLubyte *Image;
  42.  
  43. static GLboolean
  44. checkExtension(const char *name)
  45. {
  46.     const char *p = (const char *) glGetString(GL_EXTENSIONS);
  47.  
  48.     while (p = strstr(p, name)) {
  49.     const char *q = p + strlen(name);
  50.  
  51.     if (*q == ' ' || *q == '\0') {
  52.         return GL_TRUE;
  53.     }
  54.     p = q;
  55.     }
  56.     return GL_FALSE;
  57. }
  58.  
  59. static void
  60. checkError(char *msg)
  61. {
  62.     GLenum err;
  63.  
  64.     while ((err = glGetError()) != GL_NO_ERROR) {
  65.     printf("Error %d at %s\n", err, msg);
  66.     }
  67. }
  68.  
  69. static void
  70. init(void)
  71. {
  72.     GLint i, j;
  73.     GLfloat f;
  74.  
  75.     glIndexFuncSGIptr = (void *) wglGetProcAddress("glIndexFuncSGI");
  76.     if (!glIndexFuncSGIptr) {
  77.         printf("Note: renderer doesn't support GL_SGI_index_func extension.\n");
  78.     }
  79.  
  80.     setPaletteIndex( 10, 0.0F, 0.5F, 0.5F );
  81.     glClearIndex( 10.0f );
  82.     for (i=11;i<240;i++) {
  83.         GLfloat t = (GLfloat) (i-11) / (GLfloat) (240-11);
  84.         setPaletteIndex( i, t, t, 0.0F );
  85.     }
  86.  
  87.     Image = (GLubyte *) malloc( 32*32*sizeof(GLubyte) );
  88.  
  89.     for (i = 0; i < 32; i++)
  90.     for (j = 0; j < 32; j++) {
  91.         double d;
  92.  
  93.         d = sqrt((i - 16) * (i - 16) + (j - 16) * (j - 16)) / 23.0;
  94.         Image[(32 * i) + j] = 11 + (int)((240 - 11) * d);
  95.     }
  96.  
  97. #ifdef GL_SGI_index_func
  98.     if (glIndexFuncSGIptr) {
  99.         /* Sanity checks */
  100.         glEnable( GL_INDEX_TEST_SGI );
  101.         (*glIndexFuncSGIptr)( GL_GEQUAL, 10.0F );
  102.         glPushAttrib( GL_COLOR_BUFFER_BIT );
  103.         glDisable( GL_INDEX_TEST_SGI );
  104.         (*glIndexFuncSGIptr)( GL_LESS, 99.0F );
  105.         glPopAttrib();
  106.         assert( glIsEnabled(GL_INDEX_TEST_SGI) );
  107.         glGetIntegerv( GL_INDEX_TEST_FUNC_SGI, &i );
  108.         assert( i==GL_GEQUAL );
  109.         glGetFloatv( GL_INDEX_TEST_REF_SGI, &f );
  110.         assert( f==10.0f );
  111.     }
  112. #endif
  113.     checkError("after init");
  114. }
  115.  
  116. static void
  117. redraw(void)
  118. {
  119.     glClear( GL_COLOR_BUFFER_BIT );
  120.  
  121.     glPushMatrix();
  122.  
  123.     glRotatef( Zrot, 0.0F, 0.0F, 1.0F );
  124.  
  125. #ifdef GL_SGI_index_func
  126.     if (glIndexFuncSGIptr) {
  127.         if (DoTest) {
  128.             glEnable( GL_INDEX_TEST_SGI );
  129.             (*glIndexFuncSGIptr)( GL_GREATER, 128.0F );
  130.         }
  131.         else {
  132.             glDisable( GL_INDEX_TEST_SGI );
  133.  
  134.         }
  135.     }
  136. #endif
  137.  
  138.     glBegin( GL_LINES );
  139.     glIndexi(  10 );   glVertex2f( -1.0F, 0.0F );
  140.     glIndexi( 240 );   glVertex2f(  1.0F, 0.0F );
  141.     glEnd();
  142.  
  143.     glBegin( GL_TRIANGLES );
  144.     glIndexi(  11 );   glVertex2f( 0.0F, 1.0F );
  145.     glIndexi( 100 );   glVertex2f( 0.5F, 0.1F );
  146.     glIndexi( 240 );   glVertex2f( -0.5F, 0.1F );
  147.     glEnd();
  148.  
  149.     glRasterPos2f( 0.5F, -0.2F );
  150.     glDrawPixels( 32, 32, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, Image );
  151.  
  152.     glPopMatrix();
  153.  
  154.     SwapBuffers(hDC);
  155.     checkError("after swap buffers");
  156. }
  157.  
  158. static void
  159. idleRedraw(void)
  160. {
  161.     Zrot += 2.0f;
  162.     redraw();
  163. }
  164.  
  165. static void
  166. resize(void)
  167. {
  168.     glViewport( 0, 0, winWidth, winHeight );
  169.     glMatrixMode( GL_PROJECTION );
  170.     glLoadIdentity();
  171.     glOrtho( -1.0F, 1.0F, -1.0F, 1.0F, -1.0F, 1.0F );
  172.     glMatrixMode( GL_MODELVIEW );
  173.     glLoadIdentity();
  174. }
  175.  
  176. /*****************************************************************/
  177.  
  178. void
  179. setPaletteIndex(int i, float r, float g, float b)
  180. {
  181.     PALETTEENTRY pe;
  182.  
  183.     pe.peRed = (BYTE) (255.0F * r);
  184.     pe.peGreen = (BYTE) (255.0F * g);
  185.     pe.peBlue = (BYTE) (255.0F * b);
  186.     pe.peFlags = PC_NOCOLLAPSE;
  187.     SetPaletteEntries(hPalette, i, 1, &pe);
  188.     UnrealizeObject(hPalette);
  189. }
  190.  
  191. void
  192. setupPalette(HDC hDC)
  193. {
  194.     PIXELFORMATDESCRIPTOR pfd;
  195.     LOGPALETTE* pPal;
  196.     int pixelFormat = GetPixelFormat(hDC);
  197.     int paletteSize;
  198.  
  199.     DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
  200.  
  201.     /*
  202.     ** Determine if a palette is needed and if so what size.
  203.     */
  204.     if (pfd.dwFlags & PFD_NEED_PALETTE ||
  205.         pfd.iPixelType == PFD_TYPE_COLORINDEX) {
  206.     paletteSize = 1 << pfd.cColorBits;
  207.     if (paletteSize > 4096) {
  208.         paletteSize = 4096;
  209.     }
  210.     } else {
  211.     return;
  212.     }
  213.  
  214.     pPal = (LOGPALETTE*)
  215.     malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
  216.     pPal->palVersion = 0x300;
  217.     pPal->palNumEntries = paletteSize;
  218.  
  219.     /*
  220.     ** Fill the logical palette with color ramps.
  221.     **
  222.     ** Set up the logical palette so that it can be realized
  223.     ** into the system palette as an identity palette.
  224.     **
  225.     ** 1) The default static entries should be present and at the right
  226.     **    location.  The easiest way to do this is to grab them from
  227.     **    the current system palette.
  228.     **
  229.     ** 2) All non-static entries should be initialized to unique values.
  230.     **    The easiest way to do this is to ensure that all of the non-static
  231.     **    entries have the PC_NOCOLLAPSE flag bit set.
  232.     */
  233.     {
  234.     int extra = paletteSize - 20;
  235.     int i;
  236.  
  237.     /*
  238.     ** Initialize static entries by copying them from the
  239.     ** current system palette.
  240.     */
  241.     GetSystemPaletteEntries(hDC, 0, paletteSize, &pPal->palPalEntry[0]);
  242.  
  243.     /*
  244.     ** Initialize any remaining non-static entries.
  245.     */
  246.     for (i=0; i<extra; ++i) {
  247.         int index = 10+i;
  248.         PALETTEENTRY *pe = &pPal->palPalEntry[index];
  249.  
  250.         pe->peRed = (BYTE) 0;
  251.         pe->peGreen = (BYTE) 0;
  252.         pe->peBlue = (BYTE) 0;
  253.         pe->peFlags = PC_NOCOLLAPSE;
  254.     }
  255.     }
  256.  
  257.     hPalette = CreatePalette(pPal);
  258.     free(pPal);
  259.  
  260.     if (hPalette) {
  261.     SelectPalette(hDC, hPalette, FALSE);
  262.     RealizePalette(hDC);
  263.     }
  264. }
  265.  
  266. void
  267. setupPixelFormat(HDC hDC)
  268. {
  269.     PIXELFORMATDESCRIPTOR pfd = {
  270.     sizeof(PIXELFORMATDESCRIPTOR),    /* size of this pfd */
  271.     1,                /* version num */
  272.     PFD_DRAW_TO_WINDOW |        /* support window */
  273.     PFD_SUPPORT_OPENGL |        /* support OpenGL */
  274.     PFD_DOUBLEBUFFER,        /* support double-buffering */
  275.     PFD_TYPE_COLORINDEX,        /* color index mode */
  276.     8,                /* 8-bit color depth */
  277.     0, 0, 0, 0, 0, 0,        /* color bits (ignored) */
  278.     0,                /* no alpha buffer */
  279.     0,                /* alpha bits (ignored) */
  280.     0,                /* no accumulation buffer */
  281.     0, 0, 0, 0,            /* accum bits (ignored) */
  282.     16,                /* depth buffer */
  283.     0,                /* no stencil buffer */
  284.     0,                /* no auxiliary buffers */
  285.     PFD_MAIN_PLANE,            /* main layer */
  286.     0,                /* reserved */
  287.     0, 0, 0,            /* no layer, visible, damage masks */
  288.     };
  289.     int SelectedPixelFormat;
  290.     BOOL retVal;
  291.  
  292.     SelectedPixelFormat = ChoosePixelFormat(hDC, &pfd);
  293.     if (SelectedPixelFormat == 0) {
  294.     MessageBox(WindowFromDC(hDC),
  295.         "ChoosePixelFormat failed\n"
  296.         "This application works best with an 8-bit\n"
  297.         "(256 color) display mode\n",
  298.         "Error",
  299.         MB_ICONERROR | MB_OK);
  300.     exit(1);
  301.     }
  302.  
  303.     retVal = SetPixelFormat(hDC, SelectedPixelFormat, &pfd);
  304.     if (retVal != TRUE) {
  305.     MessageBox(WindowFromDC(hDC), "SetPixelFormat failed", "Error",
  306.         MB_ICONERROR | MB_OK);
  307.     exit(1);
  308.     }
  309. }
  310.  
  311. LRESULT APIENTRY
  312. WndProc(
  313.     HWND hWnd,
  314.     UINT message,
  315.     WPARAM wParam,
  316.     LPARAM lParam)
  317. {
  318.     switch (message) {
  319.     case WM_CREATE:
  320.     /*
  321.     ** Set up for OpenGL rendering.  Bind the rendering context to
  322.     ** the same device context that the palette will be selected into.
  323.     */
  324.     hDC = GetDC(hWnd);
  325.     setupPixelFormat(hDC);
  326.     setupPalette(hDC);
  327.     hGLRC = wglCreateContext(hDC);
  328.     wglMakeCurrent(hDC, hGLRC);
  329.     if (!checkExtension("SGI_index_func")) {
  330.         char message[1024];
  331.  
  332.         sprintf(message,
  333.         "SGI_index_func is required by this application\n"
  334.         "but is not supported by the current OpenGL renderer.\n\n"
  335.         "Vendor: %s\nRenderer: %s\nVersion: %s",
  336.         glGetString(GL_VENDOR),
  337.         glGetString(GL_RENDERER),
  338.         glGetString(GL_VERSION));
  339.  
  340.         wglMakeCurrent(NULL, NULL);
  341.         wglDeleteContext(hGLRC);
  342.         hGLRC = NULL;
  343.  
  344.         MessageBox(hWnd, message, "OpenGL Extension Required",
  345.             MB_ICONERROR | MB_OK);
  346.         exit(1);
  347.     }
  348.     init();
  349.     idleFunc = idleRedraw;
  350.     return 0;
  351.     case WM_DESTROY:
  352.     /*
  353.     ** Finish OpenGL rendering.
  354.     */
  355.     idleFunc = NULL;
  356.     if (hGLRC) {
  357.         wglMakeCurrent(NULL, NULL);
  358.         wglDeleteContext(hGLRC);
  359.         hGLRC = NULL;
  360.     }
  361.     ReleaseDC(hWnd, hDC);
  362.     PostQuitMessage(0);
  363.     return 0;
  364.     case WM_SIZE:
  365.     if (hGLRC) {
  366.         winWidth = (int) LOWORD(lParam);
  367.         winHeight = (int) HIWORD(lParam);
  368.         resize();
  369.         return 0;
  370.     }
  371.     case WM_PALETTECHANGED:
  372.     /*
  373.     ** Update palette mapping if this *is not* the active window.
  374.     */
  375.     if (hGLRC && hPalette && (HWND) wParam != hWnd) {
  376.         UnrealizeObject(hPalette);
  377.         SelectPalette(hDC, hPalette, FALSE);
  378.         RealizePalette(hDC);
  379.         redraw();
  380.         return 0;
  381.     }
  382.     break;
  383.     case WM_QUERYNEWPALETTE:
  384.     /*
  385.     ** Update palette mapping if this *is* the active window.
  386.     */
  387.     if (hGLRC && hPalette) {
  388.         UnrealizeObject(hPalette);
  389.         SelectPalette(hDC, hPalette, FALSE);
  390.         RealizePalette(hDC);
  391.         redraw();
  392.         return TRUE;
  393.     }
  394.     break;
  395.     case WM_PAINT:
  396.     /*
  397.     ** Update the window.  Don't use the device context returned by
  398.     ** BeginPaint as it won't have the right palette selected into it.
  399.     */
  400.     if (hGLRC) {
  401.         PAINTSTRUCT ps;
  402.  
  403.         BeginPaint(hWnd, &ps);
  404.         redraw();
  405.         EndPaint(hWnd, &ps);
  406.         return 0;
  407.     }
  408.     break;
  409.     case WM_CHAR:
  410.     switch ((int)wParam) {
  411.     case VK_ESCAPE:
  412.         DestroyWindow(hWnd);
  413.         return 0;
  414.     case VK_SPACE:
  415.         DoTest = !DoTest;
  416.         break;
  417.     default:
  418.         break;
  419.     }
  420.     break;
  421.     default:
  422.     break;
  423.     }
  424.  
  425.     /* Deal with any unprocessed messages */
  426.     return DefWindowProc(hWnd, message, wParam, lParam);
  427. }
  428.  
  429. int APIENTRY
  430. WinMain(
  431.     HINSTANCE hCurrentInst,
  432.     HINSTANCE hPreviousInst,
  433.     LPSTR lpszCmdLine,
  434.     int nCmdShow)
  435. {
  436.     WNDCLASS wndClass;
  437.     HWND hWnd;
  438.     MSG msg;
  439.  
  440.     /* Define and register a window class */
  441.     wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  442.     wndClass.lpfnWndProc = WndProc;
  443.     wndClass.cbClsExtra = 0;
  444.     wndClass.cbWndExtra = 0;
  445.     wndClass.hInstance = hCurrentInst;
  446.     wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  447.     wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  448.     wndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
  449.     wndClass.lpszMenuName = NULL;
  450.     wndClass.lpszClassName = className;
  451.     RegisterClass(&wndClass);
  452.  
  453.     /* Figure out a default size for the window */
  454.     winWidth = GetSystemMetrics(SM_CYSCREEN) / 3;
  455.     winHeight = GetSystemMetrics(SM_CYSCREEN) / 3;
  456.  
  457.     /* Create a window of the previously defined class */
  458.     hWnd = CreateWindow(
  459.     className,        /* Window class's name */
  460.     windowName,        /* Title bar text */
  461.     WS_OVERLAPPEDWINDOW |    /* The window's style */
  462.     WS_CLIPCHILDREN |
  463.     WS_CLIPSIBLINGS,
  464.     winX, winY,        /* Position */
  465.     winWidth, winHeight,    /* Size */
  466.     NULL,            /* Parent window's handle */
  467.     NULL,            /* Menu handle */
  468.     hCurrentInst,        /* Instance handle */
  469.     NULL);            /* No additional data */
  470.  
  471.     /* Map the window to the screen */
  472.     ShowWindow(hWnd, nCmdShow);
  473.  
  474.     /* Force the window to repaint itself */
  475.     UpdateWindow(hWnd);
  476.  
  477.     /* Process Messages */
  478.     while (1) {
  479.     /* execute the idle function while there are no messages to process */
  480.     while (idleFunc &&
  481.            PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == FALSE)
  482.     {
  483.         (*idleFunc)();
  484.     }
  485.     if (GetMessage(&msg, NULL, 0, 0) != TRUE) {
  486.         break;
  487.     }
  488.     TranslateMessage(&msg);
  489.     DispatchMessage(&msg);
  490.     }
  491.  
  492.     return msg.wParam;
  493. }
  494.  
  495. 
  496.